package robocup.component.coach;

import java.util.LinkedList;

import robocup.component.PConf;

public class PlayerTypeAnalyserProcess extends Thread {
	
	public void setPConfs(PConf[] confs){
		this.setDeviations(confs);
		this.all = confs;
	}
	
	PConf[] all = new PConf[11];
	
	
	

	public void setPlayingTypes(PConf[] p) {
		this.playingTypes = p;
	}
	
	private PConf[] playingTypes;
	
	
	
	public void runOld() {
		long startTime = System.nanoTime();
		
		
		// TODO try this again with true
		
		// will hold a list of players later
		LinkedList<PConf> remainingConfs = new LinkedList<PConf>();
		
		
		


		confs = playingTypes;
		System.out.println("finished. it took: " + (System.nanoTime() - startTime));
		

	}
	
	public void run() {
		
		long startTime = System.nanoTime();
		
		
		LinkedList<PConf> allConfs = new LinkedList<PConf>();
		for(int i = 1; i < all.length; i++) {
			allConfs.add(all[i]);
		}
		
		confs = new PConf[11];
		
		confs[2] = getBestRemainingForPlayer(2,allConfs);
		confs[3] = getBestRemainingForPlayer(3,allConfs);
		confs[4] = getBestRemainingForPlayer(4,allConfs);
		confs[1] = getBestRemainingForPlayer(1,allConfs);
		confs[6] = getBestRemainingForPlayer(6,allConfs);
		confs[5] = getBestRemainingForPlayer(5,allConfs);
		confs[7] = getBestRemainingForPlayer(7,allConfs);
		confs[9] = getBestRemainingForPlayer(9,allConfs);
		confs[8] = getBestRemainingForPlayer(8,allConfs);
		confs[10] = getBestRemainingForPlayer(10,allConfs);
		
		System.out.println("finished. it took: " + (System.nanoTime() - startTime));
		
		
	}
	
	
	
	// beware!! removes one element from the list!!!!
	public PConf getBestRemainingForPlayer(int player, LinkedList<PConf> remainingPConfs) {
		double max = 0;
		PConf best = null;
		
		for(PConf conf : remainingPConfs) {
			double ass = getEvaluation(player,conf);
			if(ass > max) {
				max = ass;
				best = conf;
			}
		}
		
		remainingPConfs.remove(best);
		return best;
	}

	
	
	public void setDeviations(PConf[] confs) {
		for(int i = 0;i < confs.length; i++) {
			if( SpeedMaxPos == -1 || confs[i].getEffectiveMaxSpeed() > SpeedMaxPos) {
				SpeedMaxPos = confs[i].getEffectiveMaxSpeed();
			}
			
			if( SpeedMaxNeg == 1000 || confs[i].getEffectiveMaxSpeed() < SpeedMaxNeg) {
				SpeedMaxNeg = confs[i].getEffectiveMaxSpeed();
			}
			
			if( StaminaIncPos == -1 || confs[i].STAMINA_INC_MAX > StaminaIncPos) {
				StaminaIncPos = confs[i].STAMINA_INC_MAX;
			}
			
			if( StaminaIncNeg == 1000 || confs[i].STAMINA_INC_MAX < StaminaIncNeg) {
				StaminaIncNeg = confs[i].STAMINA_INC_MAX;
			}
			
			if( KickablePos == -1 || confs[i].KICKABLE_MARGIN > KickablePos) {
				KickablePos = confs[i].KICKABLE_MARGIN;
			}
			
			if( KickableNeg == 1000 || confs[i].KICKABLE_MARGIN < KickableNeg) {
				KickableNeg = confs[i].KICKABLE_MARGIN;
			}
			
			if( KickRandPos == -1 || confs[i].KICK_RAND > KickRandPos) {
				KickRandPos = confs[i].KICK_RAND;
			}
			
			if( KickRandNeg == 1000 || confs[i].KICK_RAND < KickRandNeg) {
				KickRandNeg = confs[i].KICK_RAND;
			}
			
			if( DashPowerPos == -1 || confs[i].DASH_POWER_RATE > DashPowerPos) {
				DashPowerPos = confs[i].DASH_POWER_RATE;
			}
			
			if( DashPowerNeg ==1000 || confs[i].DASH_POWER_RATE < DashPowerNeg) {
				DashPowerNeg = confs[i].DASH_POWER_RATE;
			}
		}
		
		System.out.println("SpeedMaxPos: " + SpeedMaxPos);
		System.out.println("SpeedMaxNeg: " + SpeedMaxNeg);
		System.out.println("StaminaIncPos: " + StaminaIncPos);
		System.out.println("StaminaIncNeg: " + StaminaIncNeg);
		System.out.println("KickablePos: " + KickablePos);
		System.out.println("KickableNeg: " + KickableNeg);
		System.out.println("KickRandPos: " + KickRandPos);
		System.out.println("KickRandNeg: " + KickRandNeg);
		System.out.println("DashPowerPos: " + DashPowerPos);
		System.out.println("DashPowerNeg: " + DashPowerNeg);
	}
	
	
	
	double SpeedMaxPos = -1;
	double SpeedMaxNeg = 1000;
	
	double StaminaIncPos  = -1;
	double StaminaIncNeg = 1000;
	
	double KickablePos = -1;
	double KickableNeg = 1000;
	
	double KickRandPos = -1;
	double KickRandNeg = 1000;
	
	double DashPowerPos = -1;
	double DashPowerNeg = 1000;
	
	
	public double getEvaluation(int p, PConf pConf) {
		int player = p + 1;
		
		PConf standart = all[0];
			
		if(( player > 1 && player <= 5 )){
			
			double SpeedMaxValue = (pConf.getEffectiveMaxSpeed() - SpeedMaxNeg) / (SpeedMaxPos - SpeedMaxNeg);
			double StaminaIncValue = (pConf.STAMINA_INC_MAX - StaminaIncNeg) / (StaminaIncPos - StaminaIncNeg);
			double KickableValue = (pConf.KICKABLE_MARGIN - KickableNeg) / (KickablePos - KickableNeg); 
			double weight = 1.5;
			
			System.out.println(player + " : " + pConf + "\n" + (weight * (4 * SpeedMaxValue + 2 * StaminaIncValue + KickableValue)));
			return weight * (4 * SpeedMaxValue + 2 * StaminaIncValue + KickableValue);
		}
		
		if (player == 7) {
      double SpeedMaxValue = (pConf.getEffectiveMaxSpeed() - SpeedMaxNeg) / (SpeedMaxPos - SpeedMaxNeg);
      double StaminaIncValue = (pConf.STAMINA_INC_MAX - StaminaIncNeg) / (StaminaIncPos - StaminaIncNeg);
      double KickableValue = (pConf.KICKABLE_MARGIN - KickableNeg) / (KickablePos - KickableNeg); 
      double weight = 1.5;
      
      System.out.println(player + " : " + pConf + "\n" + (weight * (4 * SpeedMaxValue + 2 * StaminaIncValue + KickableValue)));
      return weight * (4 * StaminaIncValue + 2 * SpeedMaxValue + KickableValue);
		  
		}
		if(player == 6 || player == 8) {
			double StaminaIncValue =(pConf.STAMINA_INC_MAX - StaminaIncNeg) / (StaminaIncPos - StaminaIncNeg);
			double weight = 1.1;
			
			System.out.println(weight * (4 * StaminaIncValue + 1 + 0.5));
			return weight * (4 * StaminaIncValue + 1 + 0.5);
		}
		
		if(player > 8 && player <= 11) {
			double kickRand = (pConf.KICK_RAND - KickRandNeg) / (KickRandPos - KickRandNeg);
			double dashPower = (pConf.DASH_POWER_RATE - DashPowerNeg) / (DashPowerPos - DashPowerNeg);
			double weight = 1.3;
			
			System.out.println(weight * (4 * (1- kickRand) + 2 * dashPower  + 0.5));
			return weight * (4 * (1-kickRand) + 2 * dashPower  + 0.5);
		}
			
			
		System.out.println("this should not happen. none og the functions was right");	
//		System.out.println("eval for " + player + " is " + 10000 * pConf.DASH_POWER_RATE * player);
		return  100000 - pConf.PLAYER_DECAY * player;
	}



	private PConf[] confs;
	
	public PConf[] getConfs() {
		PConf[] ret = confs;
		confs = null;
		return ret;
	}
	
	public boolean hasConfs() {
		return confs != null;
	}
	
	
	
}
